! ==============================================================================
! This file is part of CUPP (Community Unified Physics Package) since 2023.
! ==============================================================================

module tracer_types_mod

  use cupp_const_mod
  use cupp_mesh_mod

  implicit none

  integer ntracers
  integer ntracers_water

  integer idx_qv
  integer idx_qc, idx_nc
  integer idx_qi, idx_ni
  integer idx_qr, idx_nr
  integer idx_qs, idx_ns
  integer idx_qg
  integer idx_qh
  integer idx_qo3
  integer idx_qso2

  character(32), allocatable :: tracer_names(:)
  character(32), allocatable :: tracer_long_names(:)
  character(32), allocatable :: tracer_units(:)
  ! Follow other model's definition:
  ! 0 - Generic tracer
  ! 1 - Prognostic chemical tracer
  ! 2 - Diagnostic chemical tracer
  integer, allocatable :: tracer_types(:)

  type tracers_type
    logical :: is_initialized = .false.
    type(cupp_mesh_type), pointer :: mesh => null()
    integer :: ntracers = 0
    real(r8), allocatable :: q(:,:,:)
    ! Some diagnostics:
    real(r8), allocatable :: qm(:,:) ! Total moisture or water substances
  contains
    procedure :: init  => tracers_init
    procedure :: clear => tracers_clear
    final :: tracers_final
  end type tracers_type

  type(tracers_type), allocatable, target :: tracers(:) ! (blocks)

contains

  subroutine tracers_init(this, mesh, ntracers)

    class(tracers_type), intent(inout) :: this
    type(cupp_mesh_type), intent(in), target :: mesh
    integer, intent(in) :: ntracers

    call this%clear()

    this%mesh => mesh
    this%ntracers = ntracers
    allocate(this%q(mesh%ncol+mesh%nhalo,mesh%nlev,ntracers))
    if (idx_qv > 0) then
      allocate(this%qm(mesh%ncol+mesh%nhalo,mesh%nlev))
    end if

    this%is_initialized = .true.

  end subroutine tracers_init

  subroutine tracers_clear(this)

    class(tracers_type), intent(inout) :: this

    if (allocated(this%q )) deallocate(this%q )
    if (allocated(this%qm)) deallocate(this%qm)

    this%is_initialized = .false.
    this%mesh => null()

  end subroutine tracers_clear

  subroutine tracers_final(this)

    type(tracers_type), intent(inout) :: this

    call this%clear()

  end subroutine tracers_final

end module tracer_types_mod
